package model;

import interfaces.ConnectorI;

import java.util.Vector;
import java.util.concurrent.Semaphore;

//import parallelpattern.Master;
//import parallelpattern.Task;

/**
 * Connection between workers/stages
 * 
 */
public class FIFOBuffer<INOUT> implements ConnectorI<INOUT> {

	// Attribute
	private Vector<INOUT> vec = null;
	private INOUT next = null;
	private Semaphore access = null;
	private Semaphore available = null;
	private boolean stopped = false;

	// Debug switch
	private boolean dbg = false;
	// private boolean dbg = true;

	/**
	 * @param idbegin
	 *            pipe
	 * @param idend
	 *            pipe
	 */
	public FIFOBuffer() {
		vec = new Vector<INOUT>();
		access = new Semaphore(1);
		available = new Semaphore(0);

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see parallelpattern.ConnectorI#recv()
	 */
	@Override
	public INOUT recv() {
		try {
			available.acquire();
			access.acquire();
			next = vec.remove(0);
			access.release();
			if (dbg)
				System.err.print("\n" + this + " Connector.recv() : " + next);
			return next;
		} catch (InterruptedException e) {
			System.err.println("\nError in Connector.recv()");
			e.printStackTrace();
			return null;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see parallelpattern.ConnectorI#send(java.lang.Object)
	 */
	@Override
	public boolean send(INOUT item) {
		try {
			access.acquire();
			vec.add(item);
			access.release();
			available.release();
			// System.out.println("FIFO "+item);
			if (dbg)
				System.err.println("\n" + this + " Connector.send()" + item);
			return true;
		} catch (InterruptedException e) {
			System.err.println("\nError in Connector.send(), item was " + item);
			e.printStackTrace();
			return false;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see parallelpattern.ConnectorI#emptyStream()
	 */
	public boolean eos() {
		return stopped && (vec.size() == 0);
	}

	/*
	 * End of Data
	 */
	public boolean eod() {
		if (vec.size() == 0) {
			return true;
		} else {
			return false;
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see parallelpattern.ConnectorI#stop()
	 */
	@Override
	public void stop() {
		stopped = true;

	}
}
